<?php

namespace app\install;

use app\Controller;
use app\RestoreMySQL;
use app\util\Mysql;
use Medoo\Medoo;

/**
 * 首页
 */
class Index extends Controller
{
    public $check_user = false;//不验证登录
    public $restrictAccess = false;//是否限制访问：true限制访问，false不限制访问

    /**
     * @return mixed|void|null
     */
    public function index()
    {
        $step = $_GET['step']??0;
        switch ($step) {
            case 2:
                session('install_error', false);
                return self::step2();
                break;
            case 3:
                if (session('install_error')) {
                    return error('环境检测未通过，不能进行下一步操作！');
                }
                return self::step3();
                break;
            case 4:
                if (session('install_error')) {
                    return error('环境检测未通过，不能进行下一步操作！');
                }
                return self::step4();
                break;
            case 5:
                if (session('install_error')) {
                    return error('初始失败！');
                }
                return self::step5();
                break;

            default:
                session('install_error', false);
                view('index',[],'install');
                break;
        }
    }

    /**
     * 第二步：环境检测
     * @return mixed
     */
    private function step2()
    {
        $data = [];
        $data['env'] = self::checkNnv();
        $data['dir'] = self::checkDir();
        $data['func'] = self::checkFunc();
        view('step2',$data,'install');
    }

    /**
     * 第三步：初始化配置
     * @return mixed
     */
    private function step3()
    {
        view('step3',[],'install');
    }


    /**
     * 第四步：执行安装
     * @return mixed
     */
    private function step4()
    {
        if (empty($_POST)) {
            return error('非法访问');
        }
        if (!is_writable(CONFIG_PATH.'/database.php')) {
            return error('[config/database.php]无读写权限！');
        }
        $data = $_POST;
        $data['type'] = 'mysql';
        $rule = [
            'hostname|服务器地址' => 'require',
            'hostport|数据库端口' => 'require|number',
            'database|数据库名称' => 'require',
            'username|数据库账号' => 'require',
            'prefix|数据库前缀' => 'regex:^[a-z0-9]{1,20}[_]{1}',
            'cover|覆盖数据库' => 'require|in:0,1',
        ];
        $validate = validate($data, $rule);
        if (true !== $validate) {
            return error($validate);
        }
        $cover = $data['cover'];
        // 不存在的数据库会导致连接失败
        $database = $data['database'];

        try{
            // 创建数据库连接
            $db_connect = new Medoo([
                'database_type' => 'mysql',
                'database_name' => $data['database'],
                'server'        => $data['hostname'],
                'username'      => $data['username'],
                'password'      => $data['password'],
                'port'          => $data['hostport'],
                'prefix'        => $data['prefix'],
            ]);

            // 检测数据库连接
            $db_connect->query('select version()')->fetchAll();
        }catch(\Exception $e){
            error('数据库连接失败，请检查数据库配置！');
        }
        $data['database'] = $database;
        // 生成配置文件
        self::mkDatabase($data);

        // 不覆盖检测是否已存在数据库
        if (!$cover) {
            $check = $db_connect->query("SELECT * FROM information_schema.schemata WHERE schema_name='{$database}'")->fetchAll();
            if ($check) {
                error('该数据库已存在，如需覆盖，请选择覆盖数据库！');
            }
        }

        // 创建数据库
        if (!$db_connect->query("CREATE DATABASE IF NOT EXISTS `{$database}` DEFAULT CHARACTER SET utf8")) {
            return error($db_connect->error);
        }

        return success('数据库连接成功');
    }

    /**
     * 第五步：数据库安装
     * @return mixed
     */
    private function step5()
    {
        $data = $_POST;
        $account = $data['account'];
        $password = $data['password'];

        $config = include CONFIG_PATH.'/database.php';
        $config = $config['mysql'];
        if (empty($config['hostname']) || empty($config['database']) || empty($config['username'])) {
            return error('请先点击测试数据库连接！');
        }
        if (empty($account) || empty($password)) {
            return error('请填写管理账号和密码！');
        }
        $rule = [
            'account|管理员账号' => 'require|alphaNum',
            'password|管理员密码' => 'require|length:6,20',
        ];
        $validate = validate(['account' => $account, 'password' => $password], $rule);
        if (true !== $validate) {
            return error($validate);
        }
        $database = Mysql::init();

        // 导入系统初始数据库结构
        // 导入SQL
        $sql_file = APP_PATH.'/backup/install.sql';
        if (file_exists($sql_file)) {
            $restore = new RestoreMySQL($config['hostname'],$config['username'],$config['password'],$config['database'], $sql_file);
            try {
                $restore->restore();
                $username = $_SESSION['username'];
                $client_ip = getClientIP();
                $timestamp = time();
                $database->insert("secure_info",["user"=>$username,"ip"=>$client_ip,"times"=>$timestamp,"content"=>"还原了数据库。"]);
            } catch (\Exception $e) {
                return error('导入SQL失败，请检查install.sql的语句是否正确,sql_file:'.$sql_file.',error：'.$e->getMessage());
            }
        }

        /** 创建用户 TODO... */


//        if (!$res) {
//            return error('管理员账号设置失败！');
//        }
        file_put_contents(INSTALL_PATH.'/install.lock', date('Y-m-d H:i:s'));
        return success('系统安装成功，欢迎您使用后台管理系统', '/');
    }

    /**
     * 环境检测
     * @return array
     */
    private function checkNnv()
    {
        $items = [
            'os'      => ['操作系统', '不限制', '类Unix', PHP_OS, 'ok'],
            'php'     => ['PHP版本', '7.1', '5.5及以上', PHP_VERSION, 'ok'],
            'gd'      => ['GD库', '2.0', '2.0及以上', '未知', 'ok'],
        ];
        if ($items['php'][3] < $items['php'][1]) {
            $items['php'][4] = 'no';
            session('install_error', true);
        }
        $tmp = function_exists('gd_info') ? gd_info() : [];
        if (empty($tmp['GD Version'])) {
            $items['gd'][3] = '未安装';
            $items['gd'][4] = 'no';
            session('install_error', true);
        } else {
            $items['gd'][3] = $tmp['GD Version'];
        }

        return $items;
    }

    /**
     * 目录权限检查
     * @return array
     */
    private function checkDir()
    {
        $items = [
            ['dir', './backup', '读写', '读写', 'ok'],
            ['dir', './public/static', '读写', '读写', 'ok'],
            ['dir', './public/upload', '读写', '读写', 'ok'],
            ['file', './config/database.php', '读写', '读写', 'ok'],
        ];
        foreach ($items as &$v) {
            if ($v[0] == 'dir') {// 文件夹
                if(!is_writable($v[1])) {
                    if(is_dir($v[1])) {
                        $v[3] = '不可写';
                        $v[4] = 'no';
                    } else {
                        $v[3] = '不存在';
                        $v[4] = 'no';
                    }
                    session('install_error', true);
                }
            } else {// 文件
                if(!is_writable($v[1])) {
                    $v[3] = '不可写';
                    $v[4] = 'no';
                    session('install_error', true);
                }
            }
        }
        return $items;
    }

    /**
     * 函数及扩展检查
     * @return array
     */
    private function checkFunc()
    {
        $items = [
            ['pdo', '支持', 'yes', '类'],
            ['pdo_mysql', '支持', 'yes', '模块'],
            ['zip', '支持', 'yes', '模块'],
            ['fileinfo', '支持', 'yes', '模块'],
            ['curl', '支持', 'yes', '模块'],
            ['file_get_contents', '支持', 'yes', '函数'],
            ['mb_strlen', '支持', 'yes', '函数'],
            ['gzopen', '支持', 'yes', '函数'],
        ];

        foreach ($items as &$v) {
            if(('类'==$v[3] && !class_exists($v[0])) || ('模块'==$v[3] && !extension_loaded($v[0])) || ('函数'==$v[3] && !function_exists($v[0])) ) {
                $v[1] = '不支持';
                $v[2] = 'no';
                session('install_error', true);
            }
        }

        return $items;
    }

    /**
     * 生成数据库配置文件
     * @return array
     */
    private function mkDatabase(array $data)
    {
        $code = <<<INFO
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: majiameng <666@majiameng.com>
// +----------------------------------------------------------------------
return [
    'mysql' => [
        'type'            => 'mysql',// 数据库类型
        'hostname'        => '{$data['hostname']}',// 服务器地址
        'database'        => '{$data['database']}',// 数据库名
        'username'        => '{$data['username']}',// 用户名
        'password'        => '{$data['password']}',// 密码
        'hostport'        => '{$data['hostport']}',// 端口
        'charset'         => 'utf8',// 数据库编码默认采用utf8
        'prefix'          => '{$data['prefix']}',// 数据库表前缀
    ],
];
INFO;
        file_put_contents(CONFIG_PATH.'/database.php', $code);
        // 判断写入是否成功
        $config = include CONFIG_PATH.'/database.php';
        if (empty($config['mysql']['database']) || $config['mysql']['database'] != $data['database']) {
            return error('[config/database.php]数据库配置写入失败！');
            exit;
        }
    }


}
